import torch
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image

# 单例模型 加载器
class MaturityPredictor:
    _instance = None
    
    def __init__(self):
        if MaturityPredictor._instance is not None:
            raise RuntimeError("请使用 get_instance() 方法获取实例")
            
        # 模型加载（仅执行一次）
        self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
        self.model = torch.load('best_apple_chengshu_model.pth', map_location=self.device)
        self.model.eval()
        
        # 预处理配置
        self.transform = transforms.Compose([
            transforms.Resize((224, 224)),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
        ])
        
        # 成熟度映射配置
        self.maturity_values = torch.tensor([75, 50, 100], device=self.device)

    @classmethod
    def get_instance(cls):
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance

def predict_maturity(image_path):
    """对外暴露的预测接口"""
    try:
        predictor = MaturityPredictor.get_instance()
        image = Image.open(image_path).convert('RGB')
        image_tensor = predictor.transform(image).unsqueeze(0).to(predictor.device)
        
        with torch.no_grad():
            output = predictor.model(image_tensor)
            probabilities = F.softmax(output, dim=1)
            return torch.sum(probabilities * predictor.maturity_values, dim=1).item()
            
    except Exception as e:
        print(f"成熟度预测失败: {str(e)}")
        return 0.0